import sys
import os
from PySide2.QtWidgets import QApplication, QMainWindow, QFileDialog, QGraphicsScene
from PySide2.QtUiTools import QUiLoader
from PySide2.QtGui import QWheelEvent, QMatrix, QImage, QPixmap
from PIL import ImageQt

sys.path.append('D:/Miniconda3/envs/pyQtApp_00/Data/grbl_Writter')
from core.text2Img import Text
from core.Img2Gcode import gcode_generate
import logging

class main_ui_update(QMainWindow): # 机器设置中的限位距离用于补偿

    def __init__(self):
        super().__init__()
        self.Grid_coe = 20
        self.font_path = "D:/Miniconda3/envs/pyQtApp_00/Data/grbl_Writter/fonts"
        self.ui = QUiLoader().load("grbl_Writer.ui")
        self.ui.resize(1080, 1250) # 初始化窗口大小

        # 图片生成类
        self.textFile = Text(self.Grid_coe)

        # Gcode生成类
        self.Gcode_generate_file = gcode_generate(self.Grid_coe)

        # 图片显示
        self.scene = QGraphicsScene()  # 创建画布
        self.ui.graphicsView.setScene(self.scene)  # 把画布添加到窗口
        self.ui.graphicsView.scale(1 / 0.4 / self.textFile.Grid, 1 / 0.4 / self.textFile.Grid)
        self.ui.graphicsView.show()

        # 菜单栏/文件
        # 导入文件按钮
        self.ui.action_txt.triggered.connect(self.import_txt)

        # 导出文件按钮
        self.ui.action_PNG.setEnabled(False)
        self.ui.action_nc.setEnabled(False)
        self.ui.action_PNG.triggered.connect(self.save_png)
        self.ui.action_nc.triggered.connect(self.save_gcode)

        # ...菜单栏/编辑

        # 菜单栏/窗口
        self.ui.preview_window.triggered.connect(self.window_page)
        self.ui.text_settings.triggered.connect(self.window_page)
        self.ui.machine_settings.triggered.connect(self.window_page)
        self.ui.pen_settings.triggered.connect(self.window_page)

        # 菜单栏/视图
        self.ui.zoom_in.triggered.connect(self.graphicsView_zoom)
        self.ui.zoom_out.triggered.connect(self.graphicsView_zoom)
        self.ui.back_view.triggered.connect(self.back_view_update)

        # ...菜单栏/配置

        # 预览
        # 字体选择下拉栏
        self.comboBox_set(self.font_path)
        self.ui.comboBox_4.currentIndexChanged.connect(self.font_choice)

        # 字体微调
        self.ui.doubleSpinBox_8.setValue(self.textFile.Text_y_Adjust)  # 字体Y微调
        self.ui.doubleSpinBox_8.editingFinished.connect(self.Text_spinBox_update)  # 字体Y微调
        self.ui.doubleSpinBox_9.setValue(self.textFile.Text_x_Adjust)  # 字体X微调
        self.ui.doubleSpinBox_9.editingFinished.connect(self.Text_spinBox_update)  # 字体X微调

        # 右下角图片更新按钮
        self.ui.pushButton.setEnabled(False)
        self.ui.pushButton.clicked.connect(self.graphicsView_flash)

        # 书写设置
        # 页边距和字体扰动设置
        self.ui.spinBox_9.setValue(self.textFile.Text_background_x / self.textFile.Grid) # 页面X
        self.ui.spinBox_10.setValue(self.textFile.Text_background_y / self.textFile.Grid) # 页面Y
        self.ui.doubleSpinBox_7.setValue(self.textFile.Text_font_size / self.textFile.Grid) # 页面字大小
        self.ui.spinBox.setValue(self.textFile.Text_left_margin / self.textFile.Grid) # 左边距
        self.ui.spinBox_2.setValue(self.textFile.Text_top_margin / self.textFile.Grid) # 上边距
        self.ui.spinBox_3.setValue(self.textFile.Text_right_margin / self.textFile.Grid) # 右边距
        self.ui.spinBox_4.setValue(self.textFile.Text_bottom_margin / self.textFile.Grid) # 下边距
        self.ui.spinBox_5.setValue(self.textFile.Text_line_spacing / self.textFile.Grid) # 行高度
        self.ui.spinBox_6.setValue(self.textFile.Text_word_spacing / self.textFile.Grid) # 字间距

        self.ui.doubleSpinBox.setValue(self.textFile.Text_line_spacing_sigma) # 行间距随机扰动
        self.ui.doubleSpinBox_3.setValue(self.textFile.Text_font_size_sigma) # 字体大小随机扰动
        self.ui.doubleSpinBox_2.setValue(self.textFile.Text_word_spacing_sigma) # 字间距随机扰动
        self.ui.doubleSpinBox_6.setValue(self.textFile.Text_perturb_x_sigma) # 笔画横向偏移随机扰动
        self.ui.doubleSpinBox_5.setValue(self.textFile.Text_perturb_y_sigma) # 笔画纵向偏移随机扰动
        self.ui.doubleSpinBox_4.setValue(self.textFile.Text_perturb_theta_sigma) # 笔画旋转偏移随机扰动

        self.ui.spinBox_9.editingFinished.connect(self.Text_spinBox_update) # 页面X
        self.ui.spinBox_10.editingFinished.connect(self.Text_spinBox_update) # 页面Y
        self.ui.doubleSpinBox_7.editingFinished.connect(self.Text_spinBox_update) # 页面字大小
        self.ui.spinBox.editingFinished.connect(self.Text_spinBox_update) # 左边距
        self.ui.spinBox_2.editingFinished.connect(self.Text_spinBox_update) # 上边距
        self.ui.spinBox_3.editingFinished.connect(self.Text_spinBox_update) # 右边距
        self.ui.spinBox_4.editingFinished.connect(self.Text_spinBox_update) # 下边距
        self.ui.spinBox_5.editingFinished.connect(self.Text_spinBox_update) # 行高度
        self.ui.spinBox_6.editingFinished.connect(self.Text_spinBox_update) # 字间距

        self.ui.doubleSpinBox.editingFinished.connect(self.Text_spinBox_update) # 行间距随机扰动
        self.ui.doubleSpinBox_3.editingFinished.connect(self.Text_spinBox_update) # 字体大小随机扰动
        self.ui.doubleSpinBox_2.editingFinished.connect(self.Text_spinBox_update) # 字间距随机扰动
        self.ui.doubleSpinBox_6.editingFinished.connect(self.Text_spinBox_update) # 笔画横向偏移随机扰动
        self.ui.doubleSpinBox_5.editingFinished.connect(self.Text_spinBox_update) # 笔画纵向偏移随机扰动
        self.ui.doubleSpinBox_4.editingFinished.connect(self.Text_spinBox_update) # 笔画旋转偏移随机扰动

        # 笔设置
        self.ui.spinBox_13.setValue(self.Gcode_generate_file.dilate) # 膨胀系数
        self.ui.spinBox_14.setValue(self.Gcode_generate_file.search_radius) # 点集连线问题查找半径

        self.ui.doubleSpinBox_12.setValue(self.Gcode_generate_file.up_pos) # 抬笔高度
        self.ui.doubleSpinBox_13.setValue(self.Gcode_generate_file.down_pos) # 落笔高度
        self.ui.spinBox_7.setValue(self.Gcode_generate_file.write_speed) # 书写速度
        self.ui.spinBox_8.setValue(self.Gcode_generate_file.move_speed) # 移动速度

        self.ui.spinBox_13.editingFinished.connect(self.Text_spinBox_update) # 膨胀系数
        self.ui.spinBox_14.editingFinished.connect(self.Text_spinBox_update)  # 点集连线问题查找半径

        self.ui.doubleSpinBox_12.editingFinished.connect(self.Text_spinBox_update)  # 抬笔高度
        self.ui.doubleSpinBox_13.editingFinished.connect(self.Text_spinBox_update)  # 落笔高度
        self.ui.spinBox_7.editingFinished.connect(self.Text_spinBox_update)  # 书写速度
        self.ui.spinBox_8.editingFinished.connect(self.Text_spinBox_update)  # 移动速度

        # 机器设置
        self.ui.doubleSpinBox_14.setValue(self.Gcode_generate_file.machine_Adjust_x) # X
        self.ui.doubleSpinBox_15.setValue(self.Gcode_generate_file.machine_Adjust_y) # Y
        self.ui.doubleSpinBox_16.setValue(self.Gcode_generate_file.machine_trans_x) # X_tr
        self.ui.doubleSpinBox_17.setValue(self.Gcode_generate_file.machine_trans_y)  # Y_tr
        self.ui.doubleSpinBox_18.setValue(self.Gcode_generate_file.machine_trans_theta)  # Theta_tr

        self.ui.doubleSpinBox_14.editingFinished.connect(self.Text_spinBox_update)  # X
        self.ui.doubleSpinBox_15.editingFinished.connect(self.Text_spinBox_update)  # Y
        self.ui.doubleSpinBox_16.editingFinished.connect(self.Text_spinBox_update)  # X_tr
        self.ui.doubleSpinBox_17.editingFinished.connect(self.Text_spinBox_update)  # Y_tr
        self.ui.doubleSpinBox_18.editingFinished.connect(self.Text_spinBox_update)  # Theta_tr

    def font_choice(self):
        if (self.sender() == self.ui.comboBox_4): # 下拉栏选项变化触发更新变量
            self.textFile.change_font(os.path.join(self.font_path, self.ui.comboBox_4.currentText()))
            self.ui.pushButton.setText("更新图像")
            logging.critical(f"font changed {self.ui.comboBox_4.currentText()}")

    def comboBox_set(self, font_dir): # 在下拉栏中显示font
        for _, dirs, files in os.walk(font_dir, topdown=False):
            self.ui.comboBox_4.addItems(files)

    def back_view_update(self): # 回中按钮
        self.ui.graphicsView.setTransformationAnchor(self.ui.graphicsView.AnchorViewCenter)
        q = QMatrix()
        q.setMatrix(1, self.ui.graphicsView.matrix().m12(), self.ui.graphicsView.matrix().m21(), 1,
                    self.ui.graphicsView.matrix().dx(), self.ui.graphicsView.matrix().dy())
        self.ui.graphicsView.setMatrix(q, False)
        self.ui.graphicsView.scale(1 / 5, 1 / 5)

    def graphicsView_flash(self): # 图片更新按钮
        if (self.ui.pushButton.text() == "更新图像"):
            self.textFile.draw_background_grid() # 根据当前textFile设置创建背景并绘制方格
            self.textFile.upgrade_settings() # 应用textFile设置
            self.images = self.textFile.img_Show() # 调用handwrite并对返回结果进行逐张预览
            self.frame = ImageQt.toqpixmap(self.images[0]) # PIL格式转QPixmap格式
            self.scene.clear() # 先清空上次的残留
            self.scene.addPixmap(self.frame) # 将返回结果的第一张预览在窗口 # ...多张翻页预览待做
            # self.back_view_update()
            logging.critical(f"graphicsView_flashed page{self.ui.tabWidget.currentIndex()}")
            self.ui.pushButton.setText("预览文字识别")
            self.ui.action_PNG.setEnabled(True)
        elif (self.ui.pushButton.text() == "预览文字识别"): # ...存在左边会贴上的bug
            self.Gcode_generate_file.import_image_from_Image(self.images[0]) # 将第一张格式转换并导入
            frame_result = self.Gcode_generate_file.Img2Gcode_main() # ...Img2Gcode主函数返回识别后图片，后续拆分为预览和导出
            qimage = QImage(frame_result.data, frame_result.shape[1], frame_result.shape[0], \
                            frame_result.shape[2]*frame_result.shape[1], QImage.Format_RGB888) # 格式转换
            self.scene.clear()  # 先清空上次的残留
            # print("here") # https://www.coder.work/article/2087717
            self.frame = QPixmap(qimage) # 格式转换
            self.scene.addPixmap(self.frame) # 将返回结果预览在窗口
            logging.critical(f"Previewed text recognition{frame_result.shape}")
            self.ui.action_nc.setEnabled(True)

    def graphicsView_zoom(self): # ...缩放按钮，滚轮缩放待做
        if (self.sender() == self.ui.zoom_in):
            self.ui.graphicsView.scale(1.2, 1.2)
        elif (self.sender() == self.ui.zoom_out):
            self.ui.graphicsView.scale(1 / 1.2, 1 / 1.2)

    def import_txt(self): # 导入文件按钮
        import_file, import_type = QFileDialog.getOpenFileName(None, "导入文本", "D:/Miniconda3/envs/pyQtApp_00/Data/grbl_Writter/texts", "*.txt")

        if (import_file == "" and import_type == ""):
            pass
        elif (import_type == "*.txt"):
            self.textFile.load_txt(import_file)
            logging.critical(f"loaded txt {import_file}")
            self.ui.pushButton.setText("更新图像")
            self.graphicsView_flash()
            self.ui.pushButton.setEnabled(True)

    def save_png(self): # 导出PNG按钮
        save_file, save_type = QFileDialog.getSaveFileName(None, "导出图片", "D:/Miniconda3/envs/pyQtApp_00/Data/grbl_Writter/images", "*.png")
        if (save_file == "" and save_type == ""):
            pass
        elif (save_type == "*.png"):
            self.textFile.img_save(save_file)
            logging.critical(f"saved png {save_file}")

    def save_gcode(self): # 导出G-code按钮
        save_file, save_type = QFileDialog.getSaveFileName(None, "导出Gcode", "D:/Miniconda3/envs/pyQtApp_00/Data/grbl_Writter/results", "*.nc;;*.gcode")
        if (save_file == "" and save_type == ""):
            pass
        elif (save_type == "*.nc" or save_type == "*.gcode"):
            self.Gcode_generate_file.gcode_generate_and_result(save_file)
        return

    def window_page(self): # 窗口切换(按钮/快捷键)
        if (self.sender() == self.ui.preview_window):
            self.ui.tabWidget.setCurrentIndex(0)
        elif (self.sender() == self.ui.text_settings):
            self.ui.tabWidget.setCurrentIndex(1)
        elif (self.sender() == self.ui.pen_settings):
            self.ui.tabWidget.setCurrentIndex(2)
        elif (self.sender() == self.ui.machine_settings):
            self.ui.tabWidget.setCurrentIndex(3)

    def Text_spinBox_update(self): # ...参数更新函数
        num = -1
        info = -1
        if (self.sender() == self.ui.spinBox):
            num = 0
            info = self.ui.spinBox.value()
            self.textFile.Text_left_margin = info * self.textFile.Grid
        elif (self.sender() == self.ui.spinBox_2):
            num = 1
            info = self.ui.spinBox_2.value()
            self.textFile.Text_top_margin = info * self.textFile.Grid
        elif (self.sender() == self.ui.spinBox_3):
            num = 2
            info = self.ui.spinBox_3.value()
            self.textFile.Text_right_margin = info * self.textFile.Grid
        elif (self.sender() == self.ui.spinBox_4):
            num = 3
            info = self.ui.spinBox_4.value()
            self.textFile.Text_bottom_margin = info * self.textFile.Grid
        elif (self.sender() == self.ui.spinBox_5):
            num = 4
            info = self.ui.spinBox_5.value()
            self.textFile.Text_line_spacing = info * self.textFile.Grid
        elif (self.sender() == self.ui.spinBox_6):
            num = 5
            info = self.ui.spinBox_6.value()
            self.textFile.Text_word_spacing = info * self.textFile.Grid
        elif (self.sender() == self.ui.spinBox_7):
            num = 6
            info = self.ui.spinBox_7.value()
            self.Gcode_generate_file.write_speed = info
        elif (self.sender() == self.ui.spinBox_8):
            num = 7
            info = self.ui.spinBox_8.value()
            self.Gcode_generate_file.move_speed = info
        elif (self.sender() == self.ui.spinBox_9):
            num = 8
            info = self.ui.spinBox_9.value()
            self.textFile.Text_background_x = info * self.textFile.Grid
        elif (self.sender() == self.ui.spinBox_10):
            num = 9
            info = self.ui.spinBox_10.value()
            self.textFile.Text_background_y = info * self.textFile.Grid
        elif (self.sender() == self.ui.spinBox_13):
            num = 10
            info = self.ui.spinBox_13.value()
            self.Gcode_generate_file.dilate = info
        elif (self.sender() == self.ui.spinBox_14):
            num = 11
            info = self.ui.spinBox_14.value()
            self.Gcode_generate_file.search_radius = info
        elif (self.sender() == self.ui.doubleSpinBox):
            num = 12
            info = self.ui.doubleSpinBox.value()
            self.textFile.Text_line_spacing_sigma = info
        elif (self.sender() == self.ui.doubleSpinBox_2):
            num = 13
            info = self.ui.doubleSpinBox_2.value()
            self.textFile.Text_word_spacing_sigma = info
        elif (self.sender() == self.ui.doubleSpinBox_3):
            num = 14
            info = self.ui.doubleSpinBox_3.value()
            self.textFile.Text_font_size_sigma = info
        elif (self.sender() == self.ui.doubleSpinBox_4):
            num = 15
            info = self.ui.doubleSpinBox_4.value()
            self.textFile.Text_perturb_theta_sigma = info
        elif (self.sender() == self.ui.doubleSpinBox_5):
            num = 16
            info = self.ui.doubleSpinBox_5.value()
            self.textFile.Text_perturb_y_sigma = info
        elif (self.sender() == self.ui.doubleSpinBox_6):
            num = 17
            info = self.ui.doubleSpinBox_6.value()
            self.textFile.Text_perturb_x_sigma = info
        elif (self.sender() == self.ui.doubleSpinBox_7):
            num = 18
            info = self.ui.doubleSpinBox_7.value()
            self.textFile.Text_font_size = int(info * self.textFile.Grid)
        elif (self.sender() == self.ui.doubleSpinBox_8):
            num = 19
            info = self.ui.doubleSpinBox_8.value()
            self.textFile.Text_y_Adjust = info
        elif (self.sender() == self.ui.doubleSpinBox_9):
            num = 20
            info = self.ui.doubleSpinBox_9.value()
            self.textFile.Text_x_Adjust = info
        elif (self.sender() == self.ui.doubleSpinBox_12):
            num = 21
            info = self.ui.doubleSpinBox_12.value()
            self.Gcode_generate_file.up_pos = info
        elif (self.sender() == self.ui.doubleSpinBox_13):
            num = 22
            info = self.ui.doubleSpinBox_13.value()
            self.Gcode_generate_file.down_pos = info
        elif (self.sender() == self.ui.doubleSpinBox_14):
            num = 23
            info = self.ui.doubleSpinBox_14.value()
            self.Gcode_generate_file.machine_Adjust_x = info
        elif (self.sender() == self.ui.doubleSpinBox_15):
            num = 24
            info = self.ui.doubleSpinBox_15.value()
            self.Gcode_generate_file.machine_Adjust_y = info
        elif (self.sender() == self.ui.doubleSpinBox_16):
            num = 25
            info = self.ui.doubleSpinBox_16.value()
            self.Gcode_generate_file.machine_trans_x = info
        elif (self.sender() == self.ui.doubleSpinBox_17):
            num = 26
            info = self.ui.doubleSpinBox_17.value()
            self.Gcode_generate_file.machine_trans_y = info
        elif (self.sender() == self.ui.doubleSpinBox_18):
            num = 27
            info = self.ui.doubleSpinBox_18.value()
            self.Gcode_generate_file.machine_trans_theta = info

        if (num >= 0 and info >= 0):
            if (num <= 11):
                logging.critical(f"spinBox{num + 1} valued {info}")
            elif (num <= 27):
                logging.critical(f"doubleSpinBox{num - 9} valued {info}")
            if ((num in [6, 7, 10, 11]) or (num in range(21,28))):
                self.ui.pushButton.setText("预览文字识别")
            else:
                self.ui.pushButton.setText("更新图像")


def main_loop():
    # application 对象
    app = QApplication(sys.argv)

    # QMainWindow对象
    mainwindow = main_ui_update()

    # 显示
    mainwindow.ui.show()

    # 循环
    sys.exit(app.exec_())


if __name__ == '__main__':
    main_loop()
